/* 此方法强依赖于axios依赖的xhr适配器, 基于axios 0.18.0对于cancelToken实现的复现，
  如果更新了axios,记得检查node_modules/axios依赖的adapter/xhr.js适配器是否废弃了对cancelToken的支持，
  xhr.js 下搜索 config.cancelToken.promise.then 如果没有结果，就是没了，因为TC39早在2016年已经驳回了这个提案。
  新版本 axios 使用 AbortController，可以继续基于 AbortController 做本地化的实现。
*/
export const Cancelable = (function() {
  var cancel = new WeakMap()
  var p = null
  var reason = ''
  return function(...query) {
    const queryLen = query.length
    let hash
    if (queryLen === 1) {
      const { url, method } = query[0]
      hash = url + method
    } else if (queryLen === 2) {
      const url = query[0]
      const { method } = query[1]
      hash = url + method
    }
    const cancelToken = {
      promise: (p = new Promise(resolve => {
        if (cancel.has(hash)) {
          cancel.get(hash)()
        }
        cancel.set(hash, (msg) => {
          reason = msg
          resolve(msg)
        })
      })),
      token: p,
      reason,
      throwIfRequested: () => {
        if (reason) {
          throw reason
        }
      }
    }
    return this({
      ...query,
      cancelToken
    })
  }
})()

/* 此方法用于打印请求时间 */
export const Logable = async function(query) {
  const host = query.baseURL || ''
  console.time(host + query.url)
  const res = await this({ ...query })
  console.timeEnd(host + query.url)
  return res
}

// 此方法用于切换baseUrl
export const UseServise = function(host) {
  return async function(query) {
    return this({ ...query, baseURL: host })
  }
}

// 切换1p为baseUrl
export const UseServise_1P = UseServise(process.env.VUE_APP_DATAURL_1P)

// 切换mock数据
export const UseMock_GCJ = UseServise('http://127.0.0.1:4523/m1/1462057-0-default/')

// 切换mock Dingtao本地api
export const UseDingtao = UseServise('http://192.168.10.20:9001/')

// 切换本地为baseUrl
export const UseLocal = UseServise('/sellerweb')

export const UseSameResult = (function() {
  const resolvers = []
  const rejects = []
  let currentStatus = 'FULFILLED'
  let componentNames = []
  const R = (...names) => {
    componentNames = names
    return function(vm, query) {
      return new Promise((resolve, reject) => {
        if (componentNames.includes(vm.$options.name) && currentStatus === 'PENDING') {
          resolvers.push(resolve)
          rejects.push(reject)
          return
        }
        currentStatus = 'PENDING'
        this({
          ...query
        }).then(res => {
          currentStatus = 'FULFILLED'
          while (componentNames.length) {
            componentNames.pop()
          }
          while (resolvers.length) {
            resolvers.pop()(res)
          }
          resolve(res)
        }).catch(err => {
          currentStatus = 'FULFILLED'
          while (componentNames.length) {
            componentNames.pop()
          }
          while (rejects.length) {
            rejects.pop()(err)
          }
          reject(err)
        })
      })
    }
  }
  return R
})()
